package eu.dominicum.ft.ui.web.jsf.view.bean;

import eu.dominicum.ft.pd.Country;
import eu.dominicum.ft.pd.FantasyTour;
import eu.dominicum.ft.pd.Location;
import eu.dominicum.ft.pd.Participant;
import eu.dominicum.ft.pd.Person;
import eu.dominicum.ft.pd.ProfessionalCyclist;
import eu.dominicum.ft.pd.Stage;
import eu.dominicum.ft.pd.boundary.FantasyTourManagement;
import eu.dominicum.ft.pd.boundary.GeneralManagement;
import eu.dominicum.ft.pd.boundary.LocationManagement;
import eu.dominicum.ft.pd.boundary.PersonManagement;
import eu.dominicum.ft.pd.mao.AssociateLocationsWithStageMAO;
import eu.dominicum.ft.pd.mao.AssociateTeamMemberByYerseyNumberMAO;
import eu.dominicum.ft.pd.mao.validator.AssociateRiderWithTeamMemberMAO;
import org.apache.myfaces.trinidad.component.core.input.CoreInputListOfValues;
import org.apache.myfaces.trinidad.component.core.input.CoreSelectOneChoice;
import org.apache.myfaces.trinidad.context.RequestContext;
import org.apache.myfaces.trinidad.event.LaunchEvent;
import org.apache.myfaces.trinidad.event.ReturnEvent;
import org.apache.myfaces.trinidad.event.RowDisclosureEvent;

import javax.annotation.PostConstruct;
import javax.ejb.EJBException;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.event.ValueChangeEvent;
import javax.faces.model.SelectItem;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

/**
 * Backing bean of the main application view.
 *
 * @author Harry Klerks
 * @since 2013M1
 */
@ManagedBean(name = "mainView")
@ViewScoped
public final class MainViewBean {

    /**
     * {@link eu.dominicum.ft.pd.boundary.LocationManagement}.
     */
    @Inject
    private LocationManagement locationManagement;

    /**
     * Boundary for {@link FantasyTour} objects.
     */
    @Inject
    private FantasyTourManagement fantasyTourManagement;
    /**
     * The ID of the selected {@link FantasyTour} object.
     */
    private Long selectedFantasyTour;

    /**
     * A binding for the drop down list of Fantasy Tours.
     */
    private CoreSelectOneChoice fantasyToursSelect;

    /**
     * The selected {@link FantasyTour} object.
     */
    private FantasyTour activeFantasyTour;

    /**
     * The active navigation1 item.
     */
    private String navigation1ActivePart;

    /**
     * The active navigation2 item.
     */
    private String navigation2ActivePart;

    /**
     * The overall rankings collection.
     */
    private RankingRowBean[] overallRankings;

    /**
     * The points rankings collection.
     */
    private RankingRowBean[] pointsRankings;

    /**
     * The climbing rankings collection.
     */
    private RankingRowBean[] climbingRankings;

    /**
     * The youth rankings collection.
     */
    private RankingRowBean[] youthRankings;

    /**
     * List of professional cyclists.
     */
    private List<ProfessionalCyclist> riders;

    /**
     * Boundary for all general objects.
     */
    @Inject
    private GeneralManagement generalManagment;

    /**
     * ID of the selected nationality.
     */
    private Long professionalCyclistNationality;

    /**
     * List of Country select items.
     */
    private List<SelectItem> countryItems;

    /**
     * Id of the selected professional cyclist.
     */
    private Long selectedProfessionalCyclist;

    /**
     * Select items to support a list of riders.
     */
    private List<SelectItem> riderSelectItems;

    /**
     * Id of the selected team member.
     */
    private Long selectedTeamMember;

    /**
     * AssociateRiderWithTeamMemberMAO.
     */
    @Inject
    private AssociateRiderWithTeamMemberMAO associateRiderWithTeamMemberMAO;

    /**
     * Personen.
     */
    private List<Person> people;

    /**
     * PersonManagement.
     */
    @Inject
    private PersonManagement personManagement;

    /**
     * Selected to location ID.
     */
    private Long selectedToLocationId;

    /**
     * List of location select items.
     */
    private List<SelectItem> locationItems;

    /**
     * Selected stage ID.
     */
    private Long selectedStageId;

    /**
     * Selected from location ID.
     */
    private Long selectedFromLocationId;

    /**
     * The total rankings collections.
     */
    private RankingRowBean[] totalRankings;

    /**
     * Stage filter value.
     */
    private Long stageFilterValue;

    /**
     * Stage select items.
     */
    private List<SelectItem> stageSelectItems;

    /**
     * Initializes this bean.
     */
    @PostConstruct
    public void init() {

        this.navigation1ActivePart = "FantasyTour";
        this.navigation2ActivePart = "Etappes";
        this.countryItems = new ArrayList<>();
        this.stageFilterValue = 0L;

        for (Country country : this.locationManagement.findAllCountries()) {
            this.countryItems.add(new SelectItem(country.getId(), country.getName()));
        }
    }

    /**
     * Note that Trinidad currently does not support JSF 2.x select items of any type.
     *
     * @return List<SelectItem>
     */
    public List<SelectItem> getFantasyTourSelectItems() {

        List<SelectItem> selectItems = null;
        List<FantasyTour> fantasyTours = this.fantasyTourManagement.findAllFantasyTours();
        if (fantasyTours != null) {
            selectItems = new ArrayList<>(fantasyTours.size());
            for (FantasyTour fantasyTour : fantasyTours) {
                selectItems.add(new SelectItem(fantasyTour.getId(), fantasyTour.getName()));
            }
        }
        return selectItems;
    }

    /**
     * .
     *
     * @return Long
     */
    public Long getSelectedFantasyTour() {
        return selectedFantasyTour;
    }

    /**
     * .
     *
     * @param newSelectedFantasyTour -
     */
    public void setSelectedFantasyTour(final Long newSelectedFantasyTour) {
        this.selectedFantasyTour = newSelectedFantasyTour;
        if (newSelectedFantasyTour == null) {
            this.activeFantasyTour = null;
        }
    }

    /**
     * Method is invoked upon return from the Make FantasyTour dialog.
     *
     * @param returnEvent -
     */
    public void onReturnMakeFantasyTour(final ReturnEvent returnEvent) {

        if (returnEvent.getReturnValue() != null) {
            FantasyTour fantasyTour = (FantasyTour) returnEvent.getReturnValue();
            RequestContext rc = RequestContext.getCurrentInstance();
            FacesContext facesContext = FacesContext.getCurrentInstance();
            if (rc.isPartialRequest(facesContext)) {
                rc.addPartialTarget(this.fantasyToursSelect);
            }
            facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,
                    "Fantasy Tour '" + fantasyTour.getName() + "' gemaakt", null));
        }
    }

    /**
     * .
     *
     * @return CoreSelectOneChoice
     */
    public CoreSelectOneChoice getFantasyToursSelect() {
        return fantasyToursSelect;
    }

    /**
     * .
     *
     * @param newFantasyToursSelect -
     */
    public void setFantasyToursSelect(final CoreSelectOneChoice newFantasyToursSelect) {
        this.fantasyToursSelect = newFantasyToursSelect;
    }

    /**
     * Handles the change event for the drop down with {@link FantasyTour} objects.
     *
     * @param valueChangeEvent -
     */
    public void onSelectFantasyTour(final ValueChangeEvent valueChangeEvent) {

        Long selectedFantasyTourId = (long) valueChangeEvent.getNewValue();

        this.activeFantasyTour = this.fantasyTourManagement.findById(selectedFantasyTourId);
    }

    @Override
    public String toString() {

        return "MainViewBean{}";
    }

    /**
     * Switches the view to display the Fantasy Tour part.
     *
     * @param actionEvent -
     */
    public void switchViewToFantasyTour(final ActionEvent actionEvent) {

        if (!this.navigation1ActivePart.equalsIgnoreCase("FantasyTour")) {
            this.navigation1ActivePart = "FantasyTour";
            this.navigation2ActivePart = "Etappes";
        }
    }

    /**
     * Switches the view to display the Tour part.
     *
     * @param actionEvent -
     */
    public void switchViewToTour(final ActionEvent actionEvent) {

        if (!this.navigation1ActivePart.equalsIgnoreCase("Tour")) {
            this.navigation1ActivePart = "Tour";
            this.navigation2ActivePart = "Etappes";
        }
    }

    /**
     * .
     *
     * @return String
     */
    public String getNavigation1ActivePart() {
        return navigation1ActivePart;
    }

    /**
     * .
     *
     * @return String
     */
    public String getNavigation2ActivePart() {
        return navigation2ActivePart;
    }

    /**
     * A reference to the currently active {@link eu.dominicum.ft.pd.FantasyTour} object.
     *
     * @return FantasyTour
     */
    public FantasyTour getActiveFantasyTour() {
        return activeFantasyTour;
    }

    /**
     * Switch the view to Stages for Fantasy Tour.
     *
     * @param actionEvent -
     */
    public void switchViewToFantasyTourStages(final ActionEvent actionEvent) {

        this.navigation2ActivePart = "Etappes";
    }

    /**
     * Switches the view to display the Stages for a Tour.
     *
     * @param actionEvent -
     */
    public void switchViewToTourStages(final ActionEvent actionEvent) {

        this.navigation2ActivePart = "Etappes";
    }

    /**
     * Switches the view to display the Teams for the Tour.
     *
     * @param actionEvent -
     */
    public void switchViewToTourTeams(final ActionEvent actionEvent) {

        this.navigation2ActivePart = "Teams";
    }

    /**
     * Switches the view to display the Participants for the Fantasy Tour.
     *
     * @param actionEvent -
     */
    public void switchViewToFantasyTourParticipants(final ActionEvent actionEvent) {

        this.navigation2ActivePart = "Deelnemers";
    }

    /**
     * Switches the view to display the Rankings for the Fantasy Tour.
     *
     * @param actionEvent -
     */
    public void switchViewToFantasyTourRankings(final ActionEvent actionEvent) {

        this.navigation2ActivePart = "Klassementen";
    }

    /**
     * .
     *
     * @param returnEvent -
     */
    public void onReturnMakeParticipant(final ReturnEvent returnEvent) {

        if (returnEvent.getReturnValue() != null) {
            Participant participant = (Participant) returnEvent.getReturnValue();
            RequestContext rc = RequestContext.getCurrentInstance();
            FacesContext facesContext = FacesContext.getCurrentInstance();
            if (rc.isPartialRequest(facesContext)) {
                rc.addPartialTarget(this.fantasyToursSelect);
            }
            facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,
                    "Deelnemer '" + participant.getPseudonym() + "' gemaakt", null));
            this.activeFantasyTour = this.fantasyTourManagement.findById(this.activeFantasyTour.getId());

        }
    }

    /**
     * Launch event handler for the make participant dialog.
     *
     * @param launchEvent -
     */
    public void onLaunchMakeParticipantDialog(final LaunchEvent launchEvent) {

        launchEvent.getDialogParameters().put("fantasyTourId", this.activeFantasyTour.getId());
    }

    /**
     * Action listener for the select-team-member-dialog launch.
     *
     * @param actionEvent -
     */
    public void onLaunchSelectTeamMemberDialog(final ActionEvent actionEvent) {

        RequestContext rc = RequestContext.getCurrentInstance();
        rc.getPageFlowScope().put("tourId", this.activeFantasyTour.getTour().getId());
    }

    /**
     * Event handler that fires on return from the select-team-member-dialog.
     *
     * @param returnEvent -
     */
    public void onReturnSelectTeamMemberDialog(final ReturnEvent returnEvent) {

        Integer selectedYerseyNumber = (Integer) returnEvent.getReturnValue();
        Long participantId = (Long) ((CoreInputListOfValues)
                returnEvent.getSource()).getAttributes().get("participantId");
        Long fantasyTeamMemberId = (Long) ((CoreInputListOfValues)
                returnEvent.getSource()).getAttributes().get("fantasyTeamMemberId");
        AssociateTeamMemberByYerseyNumberMAO associateTeamMemberByYerseyNumberMAO =
                new AssociateTeamMemberByYerseyNumberMAO(this.activeFantasyTour.getId(),
                        participantId, fantasyTeamMemberId, selectedYerseyNumber);
        this.fantasyTourManagement.associateTeamMemberByYerseyNumber(associateTeamMemberByYerseyNumberMAO);
        this.refreshActiveFantasyTour();
        FacesContext facesContext = FacesContext.getCurrentInstance();
        facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,
                "Rugnummer '" + selectedYerseyNumber + "' gekoppeld aan Coureur", null));
    }

    /**
     * Event handler that fires when the value of a yersey number changes.
     *
     * @param valueChangeEvent -
     */
    public void onChangeTeamMemberSelection(final ValueChangeEvent valueChangeEvent) {

        Long newYerseyNumberInput = (Long) valueChangeEvent.getNewValue();

        Long participantId = (Long) ((CoreInputListOfValues)
                valueChangeEvent.getSource()).getAttributes().get("participantId");
        Long fantasyTeamMemberId = (Long) ((CoreInputListOfValues)
                valueChangeEvent.getSource()).getAttributes().get("fantasyTeamMemberId");
        AssociateTeamMemberByYerseyNumberMAO associateTeamMemberByYerseyNumberMAO =
                new AssociateTeamMemberByYerseyNumberMAO(this.activeFantasyTour.getId(),
                        participantId, fantasyTeamMemberId, newYerseyNumberInput.intValue());
        FacesContext facesContext = FacesContext.getCurrentInstance();
        try {
            this.fantasyTourManagement.associateTeamMemberByYerseyNumber(associateTeamMemberByYerseyNumberMAO);
            this.refreshActiveFantasyTour();
            facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,
                    "Rugnummer '" + newYerseyNumberInput + "' gekoppeld aan Coureur", null));
        } catch (EJBException eex) {
            facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    "Rugnummer '" + newYerseyNumberInput + "' is ongeldig", null));
        }
    }

    /**
     * Refresh the active {@link FantasyTour} object in the model.
     */
    private void refreshActiveFantasyTour() {

        this.activeFantasyTour = this.fantasyTourManagement.findById(this.selectedFantasyTour);
    }

    /**
     * Event handler that fires on return from the Make Stage Result dialog.
     *
     * @param returnEvent -
     */
    public void onReturnMakeStageResult(final ReturnEvent returnEvent) {

        FacesContext facesContext = FacesContext.getCurrentInstance();
        facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,
                "Uitslag gemaakt", null));
        this.refreshActiveFantasyTour();
    }

    /**
     * Event handler that fires on launch of the Make Stage Result Dialog.
     *
     * @param launchEvent -
     */
    public void onLaunchMakeStageResultDialog(final LaunchEvent launchEvent) {

        FacesContext facesContext = FacesContext.getCurrentInstance();
        String stageId = ((HttpServletRequest) facesContext.getExternalContext().getRequest()).getParameter("stageId");
        String stageSequence = ((HttpServletRequest) facesContext.getExternalContext().getRequest()).getParameter("stageSequence");
        launchEvent.getDialogParameters().put("stageId", stageId);
        launchEvent.getDialogParameters().put("stageSequence", stageSequence);
        launchEvent.getDialogParameters().put("configuration", this.activeFantasyTour.getConfiguration());
        launchEvent.getDialogParameters().put("fantasyTourId", this.activeFantasyTour.getId());
    }

    /**
     * Event handler that fires on return from the calculate-scores-for-stage-dialog view.
     *
     * @param returnEvent -
     */
    public void onReturnCalculateScoresDialog(final ReturnEvent returnEvent) {

        FacesContext facesContext = FacesContext.getCurrentInstance();
        facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,
                "Scores (her)berekend", null));
    }

    /**
     * Event handler that fires on launch of the calculate-scores-for-stage-dialog view.
     *
     * @param launchEvent -
     */
    public void onLaunchCalculateScoresDialog(final LaunchEvent launchEvent) {

        FacesContext facesContext = FacesContext.getCurrentInstance();
        String fantasyStageId = ((HttpServletRequest) facesContext.getExternalContext().getRequest()).getParameter("fantasyStageId");
        String fantasyStageSequence = ((HttpServletRequest) facesContext.getExternalContext().getRequest()).getParameter("fantasyStageSequence");
        launchEvent.getDialogParameters().put("fantasyStageId", fantasyStageId);
        launchEvent.getDialogParameters().put("fantasyStageSequence", fantasyStageSequence);
    }

    /**
     * Event handler that fires when the 'Bereken' button on the overall rankings is clicked.
     *
     * @param actionEvent -
     */
    public void onCalculateOverallRankings(final ActionEvent actionEvent) {

        Vector rankings = this.fantasyTourManagement.calculateOverallRankings(this.selectedFantasyTour);
        this.overallRankings = new RankingRowBean[rankings.size()];
        Iterator iterator = rankings.iterator();
        Integer sequence = 0;
        while (iterator.hasNext()) {
            Object[] objects = (Object[]) iterator.next();
            RankingRowBean rankingRowBean = new RankingRowBean();
            rankingRowBean.setRank(sequence + 1);
            rankingRowBean.setParticipant((Participant) objects[0]);
            rankingRowBean.setTotalPoints((Long) objects[1]);
            this.overallRankings[sequence++] = rankingRowBean;
        }
    }

    /**
     * .
     *
     * @return RankingRowBean[]
     */
    public RankingRowBean[] getOverallRankings() {
        return overallRankings;
    }

    /**
     * .
     *
     * @return RankingRowBean[]
     */
    public RankingRowBean[] getPointsRankings() {
        return pointsRankings;
    }

    /**
     * Event handler that fires when the 'Bereken' button on the points rankings is clicked.
     *
     * @param actionEvent -
     */
    public void onCalculatePointsRankings(final ActionEvent actionEvent) {

        Vector rankings = this.fantasyTourManagement.calculatePointsRankings(this.selectedFantasyTour);
        this.pointsRankings = new RankingRowBean[rankings.size()];
        Iterator iterator = rankings.iterator();
        Integer sequence = 0;
        while (iterator.hasNext()) {
            Object[] objects = (Object[]) iterator.next();
            RankingRowBean rankingRowBean = new RankingRowBean();
            rankingRowBean.setRank(sequence + 1);
            rankingRowBean.setParticipant((Participant) objects[0]);
            rankingRowBean.setTotalPoints((Long) objects[1]);
            this.pointsRankings[sequence++] = rankingRowBean;
        }
    }

    /**
     * .
     *
     * @return RankingRowBean[]
     */
    public RankingRowBean[] getClimbingRankings() {
        return climbingRankings;
    }

    /**
     * Event handler that fires when the 'Bereken' button on the climbing rankings is clicked.
     *
     * @param actionEvent -
     */
    public void onCalculateClimbingRankings(final ActionEvent actionEvent) {

        Vector rankings = this.fantasyTourManagement.calculateClimbingRankings(this.selectedFantasyTour);
        this.climbingRankings = new RankingRowBean[rankings.size()];
        Iterator iterator = rankings.iterator();
        Integer sequence = 0;
        while (iterator.hasNext()) {
            Object[] objects = (Object[]) iterator.next();
            RankingRowBean rankingRowBean = new RankingRowBean();
            rankingRowBean.setRank(sequence + 1);
            rankingRowBean.setParticipant((Participant) objects[0]);
            rankingRowBean.setTotalPoints((Long) objects[1]);
            this.climbingRankings[sequence++] = rankingRowBean;
        }
    }

    /**
     * .
     *
     * @return RankingRowBean[]
     */
    public RankingRowBean[] getYouthRankings() {
        return youthRankings;
    }

    /**
     * Event handler that fires when the 'Bereken' button on the youth rankings is clicked.
     *
     * @param actionEvent -
     */
    public void onCalculateYouthRankings(final ActionEvent actionEvent) {

        Vector rankings = this.fantasyTourManagement.calculateYouthRankings(this.selectedFantasyTour);
        this.youthRankings = new RankingRowBean[rankings.size()];
        Iterator iterator = rankings.iterator();
        Integer sequence = 0;
        while (iterator.hasNext()) {
            Object[] objects = (Object[]) iterator.next();
            RankingRowBean rankingRowBean = new RankingRowBean();
            rankingRowBean.setRank(sequence + 1);
            rankingRowBean.setParticipant((Participant) objects[0]);
            rankingRowBean.setTotalPoints((Long) objects[1]);
            this.youthRankings[sequence++] = rankingRowBean;
        }
    }

    /**
     * Event handler that fires when the 'Onthul naam' link is clicked.
     *
     * @param actionEvent -
     */
    public void onRevealRealName(final ActionEvent actionEvent) {

        FacesContext facesContext = FacesContext.getCurrentInstance();
        Long participantId =
                Long.parseLong(facesContext.getExternalContext().getRequestParameterMap().get("participantId"));
        this.fantasyTourManagement.revealParticpantRealName(this.selectedFantasyTour, participantId);
        this.refreshActiveFantasyTour();
    }

    /**
     * Switches the view to display the Algemeen part.
     *
     * @param actionEvent -
     */
    public void switchViewToAlgemeen(final ActionEvent actionEvent) {

        if (!this.navigation1ActivePart.equalsIgnoreCase("Algemeen")) {
            this.navigation1ActivePart = "Algemeen";
            this.navigation2ActivePart = "Peloton";
            this.refreshRiders();
        }
    }

    /**
     * Switches the view to display the Peloton.
     *
     * @param actionEvent -
     */
    public void switchViewToAlgemeenPeloton(final ActionEvent actionEvent) {

        this.navigation2ActivePart = "Peloton";
        this.refreshRiders();
    }

    /**
     * Refresh the list of riders.
     */
    private void refreshRiders() {

        this.riders = this.generalManagment.findAllProfessionalCyclists();
    }

    /**
     * .
     *
     * @param newRiders -
     */
    public void setRiders(final List<ProfessionalCyclist> newRiders) {
        this.riders = newRiders;
    }

    /**
     * .
     *
     * @return List<ProfessionalCyclist>
     */
    public List<ProfessionalCyclist> getRiders() {
        return riders;
    }

    /**
     * .
     *
     * @param newProfessionalCyclistNationality
     *         -
     */
    public void setProfessionalCyclistNationality(final Long newProfessionalCyclistNationality) {
        this.professionalCyclistNationality = newProfessionalCyclistNationality;
    }

    /**
     * .
     *
     * @return Long
     */
    public Long getProfessionalCyclistNationality() {
        return professionalCyclistNationality;
    }

    /**
     * .
     *
     * @param newCountryItems -
     */
    public void setCountryItems(final List<SelectItem> newCountryItems) {
        this.countryItems = newCountryItems;
    }

    /**
     * .
     *
     * @return List<SelectItem>
     */
    public List<SelectItem> getCountryItems() {
        return countryItems;
    }

    /**
     * Event handler that fires when a row in the riders view expand or collapses.
     *
     * @param event -
     */
    public void onCollapseOrExpandRiderRow(final RowDisclosureEvent event) {

        if (event.getAddedSet().getSize() > 0) {
            //Means that detail stamp is expanding
            Integer rowNumber = (Integer) event.getAddedSet().iterator().next();
            this.professionalCyclistNationality = this.riders.get(rowNumber).getNationality().getId();
            this.selectedProfessionalCyclist = this.riders.get(rowNumber).getId();
        }
    }

    /**
     * Event handler that fires when the change button on professional cyclist is clicked.
     *
     * @param actionEvent -
     */
    public void onChangeRider(final ActionEvent actionEvent) {

        this.generalManagment.changeProfessionalCyclistNationality(this.selectedProfessionalCyclist,
                this.professionalCyclistNationality);
        this.refreshRiders();
    }

    /**
     * .
     *
     * @param newSelectedProfessionalCyclist -
     */
    public void setSelectedProfessionalCyclist(final Long newSelectedProfessionalCyclist) {
        this.selectedProfessionalCyclist = newSelectedProfessionalCyclist;
    }

    /**
     * .
     *
     * @return Long
     */
    public Long getSelectedProfessionalCyclist() {
        return selectedProfessionalCyclist;
    }

    /**
     * .
     *
     * @param newRiderSelectItems -
     */
    public void setRiderSelectItems(final List<SelectItem> newRiderSelectItems) {
        this.riderSelectItems = newRiderSelectItems;
    }

    /**
     * .
     *
     * @return List<SelectItem>
     */
    public List<SelectItem> getRiderSelectItems() {

        if (this.riderSelectItems == null || this.riderSelectItems.isEmpty()) {
            this.refreshRiders();
            this.riderSelectItems = new ArrayList<>();
            if (this.riders != null) {
                for (ProfessionalCyclist professionalCyclist : this.riders) {
                    SelectItem newSelectItem = new SelectItem();
                    newSelectItem.setValue(professionalCyclist.getId());
                    newSelectItem.setLabel(professionalCyclist.getPerson().getOrderedName());
                    this.riderSelectItems.add(newSelectItem);
                }
            }
        }
        return riderSelectItems;
    }

    /**
     * .
     *
     * @param newSelectedTeamMember -
     */
    public void setSelectedTeamMember(final Long newSelectedTeamMember) {
        this.selectedTeamMember = newSelectedTeamMember;
    }

    /**
     * .
     *
     * @return Long
     */
    public Long getSelectedTeamMember() {
        return selectedTeamMember;
    }

    /**
     * Action handler that fires when a rider is associated with a team member.
     *
     * @return String
     */
    public String onAssociateRiderWithTeamMember() {

        this.associateRiderWithTeamMemberMAO.setTeamMemberId(this.selectedTeamMember);
        this.associateRiderWithTeamMemberMAO.setProfessionalCyclistId(this.selectedProfessionalCyclist);
        this.associateRiderWithTeamMemberMAO.setFantasyTourId(this.selectedFantasyTour);
        this.fantasyTourManagement.associateRiderWithTeamMember(associateRiderWithTeamMemberMAO);
        this.refreshActiveFantasyTour();
        return null;
    }

    /**
     * .
     *
     * @param actionEvent -
     */
    public void switchViewToAlgemeenMensen(final ActionEvent actionEvent) {

        this.navigation2ActivePart = "Mensen";
        this.refreshPeople();
    }

    /**
     * Refresh the list of people.
     */
    private void refreshPeople() {

        this.people = this.personManagement.findAllPersons();
    }

    /**
     * .
     *
     * @param newPeople -
     */
    public void setPeople(final List<Person> newPeople) {
        this.people = newPeople;
    }

    /**
     * .
     *
     * @return List<People>
     */
    public List<Person> getPeople() {

        if (this.people == null) {
            this.refreshPeople();
        }
        return people;
    }

    /**
     * Event handler that fires on return from the make-person dialog view.
     *
     * @param returnEvent -
     */
    public void onReturnFromMakePersonDialog(final ReturnEvent returnEvent) {

        if (returnEvent.getReturnValue() != null) {
            Person newPerson = (Person) returnEvent.getReturnValue();
            FacesContext facesContext = FacesContext.getCurrentInstance();
            facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,
                    "Persoon '" + newPerson.getFullname() + "' gemaakt", null));
            this.refreshPeople();
        }
    }

    /**
     * Event handler that fires on launch of the make-person-dialog view.
     *
     * @param launchEvent -
     */
    public void onLaunchMakePersonDialog(final LaunchEvent launchEvent) {
    }

    /**
     * .
     *
     * @return String
     */
    public String getRowSelectionMensen() {

        HttpServletRequest httpServletRequest = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
        if (httpServletRequest.isUserInRole("admin")) {
            return "single";
        } else {
            return "none";
        }
    }

    /**
     * Return event handler that fires when returned from the make-professional-cyclist-dialog view.
     *
     * @param returnEvent -
     */
    public void onReturnFromMakeProfessionalCyclistDialog(final ReturnEvent returnEvent) {

        if (returnEvent.getReturnValue() != null) {
            ProfessionalCyclist newProfessionalCyclist = (ProfessionalCyclist) returnEvent.getReturnValue();
            FacesContext facesContext = FacesContext.getCurrentInstance();
            facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,
                    "Coureur '" + newProfessionalCyclist.getPerson().getFullname() + "' gemaakt", null));
            this.refreshRiders();
        }
    }

    /**
     * Launch event handler that fires when the make-professional-cyclist-dialog is launched.
     *
     * @param launchEvent -
     */
    public void onLaunchMakeProfessionalCyclistDialog(final LaunchEvent launchEvent) {
    }

    /**
     * .
     *
     * @param newSelectedToLocationId -
     */
    public void setSelectedToLocationId(final Long newSelectedToLocationId) {
        this.selectedToLocationId = newSelectedToLocationId;
    }

    /**
     * .
     *
     * @return Long
     */
    public Long getSelectedToLocationId() {
        return selectedToLocationId;
    }

    /**
     * .
     *
     * @return List<SelectItem>
     */
    public List<SelectItem> getLocationItems() {

        List<Location> locations = this.locationManagement.findAllLocations();
        this.locationItems = new ArrayList<>();

        for (Location location : locations) {
            this.locationItems.add(new SelectItem(location.getId(), location.getName() + " (" + location.getCountry().getCountryCode() + ")"));
        }
        return locationItems;
    }

    /**
     * .
     *
     * @return String
     */
    public String onAssociateLocationsWithStage() {

        AssociateLocationsWithStageMAO associateLocationsWithStageMAO = new AssociateLocationsWithStageMAO();
        associateLocationsWithStageMAO.setStageId(this.selectedStageId);
        associateLocationsWithStageMAO.setFromLocationId(this.selectedFromLocationId);
        associateLocationsWithStageMAO.setToLocationId(this.selectedToLocationId);
        associateLocationsWithStageMAO.setFantasyTourId(this.selectedFantasyTour);
        this.fantasyTourManagement.associateLocationsWithStage(associateLocationsWithStageMAO);
        this.refreshActiveFantasyTour();

        return null;
    }

    /**
     * .
     *
     * @param newSelectedStageId -
     */
    public void setSelectedStageId(final Long newSelectedStageId) {
        this.selectedStageId = newSelectedStageId;
    }

    /**
     * .
     *
     * @return Long
     */
    public Long getSelectedStageId() {
        return selectedStageId;
    }

    /**
     * .
     *
     * @param newSelectedFromLocationId -
     */
    public void setSelectedFromLocationId(final Long newSelectedFromLocationId) {
        this.selectedFromLocationId = newSelectedFromLocationId;
    }

    /**
     * .
     *
     * @return Long
     */
    public Long getSelectedFromLocationId() {
        return selectedFromLocationId;
    }

    /**
     * .
     *
     * @return RankingRowBean[]
     */
    public RankingRowBean[] getTotalRankings() {
        return totalRankings;
    }

    /**
     * Action event that fires when the 'Bereken' button is clicked.
     *
     * @param actionEvent -
     */
    public void onCalculateTotalRankings(final ActionEvent actionEvent) {

        Vector rankings = this.fantasyTourManagement.calculateTotalRankings(this.selectedFantasyTour, this.stageFilterValue);
        this.totalRankings = new RankingRowBean[rankings.size()];
        Iterator iterator = rankings.iterator();
        Integer sequence = 0;
        while (iterator.hasNext()) {
            Object[] objects = (Object[]) iterator.next();
            RankingRowBean rankingRowBean = new RankingRowBean();
            rankingRowBean.setRank(sequence + 1);
            rankingRowBean.setParticipant((Participant) objects[0]);
            rankingRowBean.setTotalPoints((Long) objects[1]);
            this.totalRankings[sequence++] = rankingRowBean;
        }
    }

    /**
     * .
     *
     * @param newStageFilterValue -
     */
    public void setStageFilterValue(final Long newStageFilterValue) {
        this.stageFilterValue = newStageFilterValue;
    }

    /**
     * .
     *
     * @return Long
     */
    public Long getStageFilterValue() {
        return stageFilterValue;
    }

    /**
     * .
     *
     * @return List<SelectItem>
     */
    public List<SelectItem> getStageSelectItems() {

        if (this.selectedFantasyTour != null) {
            this.stageSelectItems = new ArrayList<>();
            for (Stage stage : this.activeFantasyTour.getTour().getStages()) {
                this.stageSelectItems.add(new SelectItem(stage.getId(), stage.toString()));
            }
        }
        return this.stageSelectItems;
    }

    public void onClickCalculateIdealTeam(ActionEvent actionEvent) {

        FacesContext facesContext = FacesContext.getCurrentInstance();
        Long participantId =
                Long.parseLong(facesContext.getExternalContext().getRequestParameterMap().get("participantId"));
        this.fantasyTourManagement.calculateIdealTeam(this.selectedFantasyTour, participantId);
        this.refreshActiveFantasyTour();
    }
}
